package com.lkd.job;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.lkd.config.TopicConfig;
import com.lkd.contract.SupplyChannel;
import com.lkd.contract.SupplyContract;
import com.lkd.emq.MqttProducer;
import com.lkd.entity.ChannelEntity;
import com.lkd.entity.VendingMachineEntity;
import com.lkd.service.ChannelService;
import com.lkd.service.VendingMachineService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.util.ShardingUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class SupplyJob {

    @Resource
    private VendingMachineService vendingMachineService;

    @Resource
    private ChannelService channelService;

    @Resource
    private MqttProducer mqttProducer;

    @XxlJob("supplyJobTask")
    public ReturnT<String> SupplyJobTask(String param) {


        //获取XXL-JOB分片信息
        ShardingUtil.ShardingVO shardingVo = ShardingUtil.getShardingVo();
        int index = shardingVo.getIndex();
        int total = shardingVo.getTotal();
        //log.info("分片总数量:{},当前分片索引:{}", total, index);

        //1.扫描售货机列表
        LambdaQueryWrapper<VendingMachineEntity> wrapper = Wrappers
                .<VendingMachineEntity>lambdaQuery()
                .eq(VendingMachineEntity::getVmStatus, 1)
                .apply(total > 1, "mod(id," + total + ") = " + index);
        List<VendingMachineEntity> machineList = vendingMachineService.list(wrapper);

        log.info("分片总数量:{},当前分片索引:{} , 查询到分片任务数据,数据id:{}", total, index, machineList.stream().map(machine -> machine.getId()).collect(Collectors.toList()));

//        SupplyContract supplyContract=new SupplyContract();
//        supplyContract.setInnerCode();

        //遍历售货机列表，计算每个售货机的补货数据
        machineList.stream()
                //遍历封装售货机补货数据
                .map(machine -> {
                    SupplyContract supplyContract = new SupplyContract();
                    supplyContract.setInnerCode(machine.getInnerCode());

                    //根据售货机编码查询售货机货道列表
                    List<ChannelEntity> channelesList = channelService.getChannelesByInnerCode(machine.getInnerCode());
                    //3.计算捕获信息
                    List<SupplyChannel> supplyChannels = getSupplyChannels(channelesList);

                    //将每个货道的补货信息封装到协议类
                    supplyContract.setSupplyData(supplyChannels);
                    return supplyContract;
                })
                //过滤掉不需要补货的售货机
                .filter(supplyContract -> CollectionUtils.isNotEmpty(supplyContract.getSupplyData()))
                //4.发送消息通知EMQ
                .forEach(supplyContract -> {
                    try {
                        log.info("发送补货消息：{}", supplyContract);
                        mqttProducer.send(TopicConfig.TASK_SUPPLY_TOPIC, 2, supplyContract);
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                        log.error("发送补货工单消息失败：{}", e.getMessage());
                    }
                });
        return ReturnT.SUCCESS;
    }


    /**
     * 计算每个货道的补货数据列表
     *
     * @param channelesList
     * @return
     */
    private List<SupplyChannel> getSupplyChannels(List<ChannelEntity> channelesList) {
        //遍历货道，计算每个货道的补货信息列表
        List<SupplyChannel> supplyChannels = channelesList.stream()
                //过滤掉不需要补货的货道
                .filter(channel -> channel.getSkuId() != 0 && channel.getMaxCapacity() - channel.getCurrentCapacity() > 0)
                //计算货道补货数据
                .map(channel -> {
                    SupplyChannel supplyChannel = new SupplyChannel();
                    supplyChannel.setSkuName(channel.getSku().getSkuName());
                    supplyChannel.setSkuImage(channel.getSku().getSkuImage());
                    supplyChannel.setSkuId(channel.getSkuId());
                    supplyChannel.setChannelId(channel.getChannelCode());
                    supplyChannel.setCapacity(channel.getMaxCapacity() - channel.getCurrentCapacity());
                    return supplyChannel;

                }).collect(Collectors.toList());
        return supplyChannels;
    }
}
